package main

import (
	"bytes"
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"time"
)

func init() {
	sql.Register("mysqlproxy", &MySQLProxyDriver{})
}

// MySQLProxyDriver 实现 driver.Driver 接口
type MySQLProxyDriver struct{}

// Open 打开一个新的连接
func (d *MySQLProxyDriver) Open(dsn string) (driver.Conn, error) {
	connName, serverURL := parseMySQLDSN(dsn)

	config := ConnConfig{
		ServerURL:  serverURL,
		Timeout:    time.Second * 30,
		DBType:     "mysql",
		Connection: connName,
	}

	return &MySQLConn{
		config: config,
		client: &http.Client{
			Timeout: config.Timeout,
		},
	}, nil
}

// 解析MySQL DSN
// 格式: [connection_name@]host:port
func parseMySQLDSN(dsn string) (connName, serverURL string) {
	connName = "default"

	// 检查是否指定了连接名称
	parts := splitAtSign(dsn)
	if len(parts) > 1 {
		connName = parts[0]
		dsn = parts[1]
	}

	// 确保URL包含协议
	if !hasProtocol(dsn) {
		dsn = "http://" + dsn
	}

	return connName, dsn
}

// MySQLConn 实现了driver.Conn接口
type MySQLConn struct {
	config        ConnConfig
	client        *http.Client
	transactionID string
}

// sendRequest 发送请求到服务器
func (c *MySQLConn) sendRequest(req SQLRequest) (*SQLResponse, error) {
	// 设置数据库类型和连接名称
	req.DBType = c.config.DBType
	req.Connection = c.config.Connection

	data, err := json.Marshal(req)
	if err != nil {
		return nil, err
	}

	httpReq, err := http.NewRequest("POST", buildRequestURL(c.config.ServerURL), bytes.NewBuffer(data))
	if err != nil {
		return nil, err
	}
	httpReq.Header.Set("Content-Type", "application/json")

	resp, err := c.client.Do(httpReq)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, fmt.Errorf("服务器错误: %s - %s", resp.Status, string(body))
	}

	var sqlResp SQLResponse
	if err := json.NewDecoder(resp.Body).Decode(&sqlResp); err != nil {
		return nil, err
	}

	if sqlResp.Error != "" {
		return nil, errors.New(sqlResp.Error)
	}

	return &sqlResp, nil
}

// Prepare 实现 driver.Conn 接口的 Prepare 方法
func (c *MySQLConn) Prepare(query string) (driver.Stmt, error) {
	req := SQLRequest{
		SQL:       query,
		Operation: "prepare",
		RequestID: c.transactionID,
	}

	resp, err := c.sendRequest(req)
	if err != nil {
		return nil, err
	}

	if len(resp.Rows) == 0 || len(resp.Rows[0]) == 0 {
		return nil, errors.New("准备语句失败: 无有效ID返回")
	}

	stmtID, ok := resp.Rows[0][0].(string)
	if !ok {
		return nil, errors.New("准备语句失败: 返回的ID格式无效")
	}

	return &MySQLStmt{
		conn:   c,
		query:  query,
		stmtID: stmtID,
	}, nil
}

// Close 实现 driver.Conn 接口的 Close 方法
func (c *MySQLConn) Close() error {
	// 如果有事务未提交，尝试回滚
	if c.transactionID != "" {
		c.rollback()
	}
	return nil
}

// Begin 实现 driver.Conn 接口的 Begin 方法
func (c *MySQLConn) Begin() (driver.Tx, error) {
	// 生成唯一事务ID
	c.transactionID = fmt.Sprintf("tx-%d", time.Now().UnixNano())

	req := SQLRequest{
		Operation: "begin",
		RequestID: c.transactionID,
	}

	_, err := c.sendRequest(req)
	if err != nil {
		c.transactionID = ""
		return nil, err
	}

	return &MySQLTx{conn: c}, nil
}

// Exec 实现扩展接口，直接执行SQL语句
func (c *MySQLConn) Exec(query string, args []driver.Value) (driver.Result, error) {
	dargs := valuesToInterface(args)
	req := SQLRequest{
		SQL:       query,
		Args:      dargs,
		Operation: "exec",
		RequestID: c.transactionID,
	}

	resp, err := c.sendRequest(req)
	if err != nil {
		return nil, err
	}

	if len(resp.Rows) == 0 || len(resp.Rows[0]) < 2 {
		return nil, errors.New("执行失败: 响应格式无效")
	}

	// 获取LastInsertId和RowsAffected
	var lastInsertID, rowsAffected int64

	if v, ok := resp.Rows[0][0].(float64); ok {
		lastInsertID = int64(v)
	}

	if v, ok := resp.Rows[0][1].(float64); ok {
		rowsAffected = int64(v)
	}

	return &MySQLResult{
		lastInsertID: lastInsertID,
		rowsAffected: rowsAffected,
	}, nil
}

// Query 实现扩展接口，直接执行查询
func (c *MySQLConn) Query(query string, args []driver.Value) (driver.Rows, error) {
	dargs := valuesToInterface(args)
	req := SQLRequest{
		SQL:       query,
		Args:      dargs,
		Operation: "query",
		RequestID: c.transactionID,
	}

	resp, err := c.sendRequest(req)
	if err != nil {
		return nil, err
	}

	return &MySQLRows{
		columns: resp.Columns,
		rows:    resp.Rows,
		rowIdx:  -1,
	}, nil
}

// rollback 执行事务回滚
func (c *MySQLConn) rollback() error {
	if c.transactionID == "" {
		return nil
	}

	req := SQLRequest{
		Operation: "rollback",
		RequestID: c.transactionID,
	}

	_, err := c.sendRequest(req)
	c.transactionID = ""
	return err
}

// commit 执行事务提交
func (c *MySQLConn) commit() error {
	if c.transactionID == "" {
		return nil
	}

	req := SQLRequest{
		Operation: "commit",
		RequestID: c.transactionID,
	}

	_, err := c.sendRequest(req)
	c.transactionID = ""
	return err
}

// MySQLResult 实现 driver.Result 接口
type MySQLResult struct {
	lastInsertID int64
	rowsAffected int64
}

// LastInsertId 返回上次插入操作的ID
func (r *MySQLResult) LastInsertId() (int64, error) {
	return r.lastInsertID, nil
}

// RowsAffected 返回受影响的行数
func (r *MySQLResult) RowsAffected() (int64, error) {
	return r.rowsAffected, nil
}

// MySQLStmt 实现 driver.Stmt 接口
type MySQLStmt struct {
	conn   *MySQLConn
	query  string
	stmtID string
}

// Close 关闭语句
func (s *MySQLStmt) Close() error {
	// 我们不在客户端关闭预处理语句，而是由服务器管理它的生命周期
	return nil
}

// NumInput 返回参数数量
func (s *MySQLStmt) NumInput() int {
	// 由于我们没有真正的MySQL解析器，无法准确知道参数数量
	return -1
}

// Exec 执行预处理语句
func (s *MySQLStmt) Exec(args []driver.Value) (driver.Result, error) {
	dargs := valuesToInterface(args)
	req := SQLRequest{
		SQL:       s.query,
		Args:      dargs,
		Operation: "exec",
		RequestID: s.conn.transactionID,
	}

	resp, err := s.conn.sendRequest(req)
	if err != nil {
		return nil, err
	}

	if len(resp.Rows) == 0 || len(resp.Rows[0]) < 2 {
		return nil, errors.New("执行失败: 响应格式无效")
	}

	// 获取LastInsertId和RowsAffected
	var lastInsertID, rowsAffected int64

	if v, ok := resp.Rows[0][0].(float64); ok {
		lastInsertID = int64(v)
	}

	if v, ok := resp.Rows[0][1].(float64); ok {
		rowsAffected = int64(v)
	}

	return &MySQLResult{
		lastInsertID: lastInsertID,
		rowsAffected: rowsAffected,
	}, nil
}

// Query 执行预处理查询
func (s *MySQLStmt) Query(args []driver.Value) (driver.Rows, error) {
	dargs := valuesToInterface(args)
	req := SQLRequest{
		SQL:       s.query,
		Args:      dargs,
		Operation: "query",
		RequestID: s.conn.transactionID,
	}

	resp, err := s.conn.sendRequest(req)
	if err != nil {
		return nil, err
	}

	return &MySQLRows{
		columns: resp.Columns,
		rows:    resp.Rows,
		rowIdx:  -1,
	}, nil
}

// MySQLRows 实现 driver.Rows 接口
type MySQLRows struct {
	columns []string
	rows    [][]interface{}
	rowIdx  int
}

// Columns 返回列名
func (r *MySQLRows) Columns() []string {
	return r.columns
}

// Close 关闭结果集
func (r *MySQLRows) Close() error {
	return nil
}

// Next 获取下一行数据
func (r *MySQLRows) Next(dest []driver.Value) error {
	r.rowIdx++
	if r.rowIdx >= len(r.rows) {
		return io.EOF
	}

	row := r.rows[r.rowIdx]
	if len(row) != len(dest) {
		return fmt.Errorf("列数不匹配: 需要 %d, 返回 %d", len(dest), len(row))
	}

	for i, v := range row {
		dest[i] = driver.Value(v)
	}

	return nil
}

// MySQLTx 实现 driver.Tx 接口
type MySQLTx struct {
	conn *MySQLConn
}

// Commit 提交事务
func (tx *MySQLTx) Commit() error {
	return tx.conn.commit()
}

// Rollback 回滚事务
func (tx *MySQLTx) Rollback() error {
	return tx.conn.rollback()
}
